package cn.tpshion.devops.node;

import cn.tpshion.devops.common.constant.RedisKey;
import cn.tpshion.devops.common.enums.MsgType;
import cn.tpshion.devops.common.enums.NodeType;
import cn.tpshion.devops.common.constant.NodeConstant;
import cn.tpshion.devops.domain.entity.MsgData;
import cn.tpshion.devops.domain.entity.NodeData;
import cn.tpshion.devops.domain.entity.SSHSecretData;
import cn.tpshion.devops.domain.entity.SecretData;
import cn.tpshion.devops.handle.SFTPHandle;
import cn.tpshion.devops.handle.SSHHandle;
import cn.tpshion.devops.node.data.SSHData;
import cn.tpshion.devops.node.data.SftpData;
import cn.tpshion.devops.node.support.NodeContext;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.Map;

@Slf4j
@Component
public class SFTPNode extends Node<SftpData> {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public NodeType nodeType() {
        return NodeType.SFTP;
    }

    @Override
    public void handle(NodeContext nodeContext) throws Exception {
        log.info("FtpNode nodeContext:{}", nodeContext);
        sseHandle.sendMessage(nodeContext, new MsgData(MsgType.INFO, "开始执行sftp节点"));
        Map<String, Object> contextData = nodeContext.getData();

        SftpData data = getData(nodeContext);

        if(StringUtils.hasText(data.getBeforeCommand())){
            SSHData sshData = new SSHData();
            BeanUtils.copyProperties(data, sshData);
            try (SSHHandle sshHandle = new SSHHandle(sshData, sseHandle, nodeContext)){
                sshHandle.exec(data.getBeforeCommand());
            }
        }

        String localPath = getLocalPath(contextData, data);
        data.setLocalPath(localPath);
        data.setRemotePath(getRemotePath(contextData, data));

        String msg = "远程地址：" + data.getRemotePath() + " 本地地址：" + localPath + " 文件名称：" + data.getFileName();
        log.info("FtpNode:{}", msg);
        sseHandle.sendMessage(nodeContext, new MsgData(MsgType.INFO, msg));

        try (SFTPHandle sftpHandle = new SFTPHandle(data, nodeContext, sseHandle)){
            if(StringUtils.hasText(data.getFileName())){
                sftpHandle.uploadFile(data);
            }else{
                sftpHandle.batchUploadFile(data);
            }
        }
    }

    private String getLocalPath(Map<String, Object> contextData, SftpData data){
        String workspace = contextData.get(NodeConstant.WORKSPACE).toString();
        String localPath = data.getLocalPath();
        if(!StringUtils.hasText(localPath)){
            return workspace;
        }
        if(localPath.contains("#workspace#")){
            return localPath.replaceAll("#workspace#", workspace);
        }
        return localPath;
    }

    private String getRemotePath(Map<String, Object> contextData, SftpData data){
        String workspace = contextData.get(NodeConstant.WORKSPACE).toString();
        String remotePath = data.getRemotePath();
        if(!StringUtils.hasText(remotePath)){
            return null;
        }
        if(remotePath.contains("#workspace#")){
            return remotePath.replaceAll("#workspace#", workspace);
        }
        return remotePath;
    }

    @Override
    protected SftpData getData(NodeContext nodeContext) {
        NodeData nodeData = nodeContext.getNodeData();
        SftpData data = JSON.parseObject(JSON.toJSONString(nodeData.getData()), SftpData.class);

        HashOperations<String, String, String> hash = redisTemplate.opsForHash();
        String value = hash.get(RedisKey.SECRET, data.getSecretName());
        SecretData secretData = JSON.parseObject(value, SecretData.class);

        SSHSecretData sshSecretData = JSON.parseObject(JSON.toJSONString(secretData.getData()), SSHSecretData.class);
        data.setHost(sshSecretData.getHost());
        data.setUsername(sshSecretData.getUsername());
        data.setPassword(sshSecretData.getPassword());
        data.setPort(sshSecretData.getPort());
        return data;
    }
}
